package main

import (
	"context"
	"fmt"
	"log"
	"net/http"
	"os"
	"os/signal"
	"syscall"
	"time"

	"gitee.com/war2001/NiuMaEasyGo/global"
	"gitee.com/war2001/NiuMaEasyGo/nm_core"
	"gitee.com/war2001/NiuMaEasyGo/nm_core/config"
	"gitee.com/war2001/NiuMaEasyGo/nm_core/initialize"
	"gitee.com/war2001/NiuMaEasyGo/nm_core/middleware"
	"github.com/gin-gonic/gin"
	"go.uber.org/zap"
)

func main() {
	// 1. 初始化配置
	if err := config.Init(); err != nil {
		log.Fatalf("初始化配置失败: %v", err)
	}

	// 2. 初始化日志
	logger := nm_core.Zap()
	defer logger.Sync()
	zap.ReplaceGlobals(logger)
	zap.L().Info("日志系统初始化成功")

	// 3. 初始化数据库
	_, err := initialize.InitDatabase()
	if err != nil {
		zap.L().Fatal("数据库初始化失败", zap.Error(err))
	}
	zap.L().Info("数据库连接初始化成功")

	// 4. 初始化Redis
	_, _, err = initialize.InitRedis()
	if err != nil {
		zap.L().Fatal("Redis初始化失败", zap.Error(err))
	}
	zap.L().Info("Redis连接初始化成功")

	// 5. 自动迁移数据库表结构
	if err := initialize.AutoMigrateDB(global.DB); err != nil {
		zap.L().Fatal("数据库表结构迁移失败", zap.Error(err))
	}
	zap.L().Info("数据库表结构迁移成功")

	// 6. 初始化WebSocket服务
	_, err = initialize.InitWebSocket()
	if err != nil {
		zap.L().Fatal("WebSocket服务初始化失败", zap.Error(err))
	}

	// 7. 初始化消息队列
	_, err = initialize.InitMessageQueue()
	if err != nil {
		zap.L().Fatal("消息队列初始化失败", zap.Error(err))
	}

	// 8. 初始化调度器
	_, err = initialize.InitScheduler()
	if err != nil {
		zap.L().Fatal("调度器初始化失败", zap.Error(err))
	}

	// 初始化分布式调度器
	if global.Config.Scheduler.Distributed.Enabled {
		err = initialize.InitDistributedScheduler()
		if err != nil {
			zap.L().Error("分布式调度器初始化失败", zap.Error(err))
		} else {
			zap.L().Info("分布式调度器初始化成功")
		}
	}

	// 9. 初始化存储服务
	_, err = initialize.InitStorage()
	if err != nil {
		zap.L().Fatal("存储服务初始化失败", zap.Error(err))
	}
	zap.L().Info("存储服务初始化成功")

	// 10. 初始化服务
	services := initialize.InitServices(global.DB, global.Redis)
	zap.L().Info("服务层初始化成功")

	// 11. 初始化工具类
	utils := initialize.InitUtils(services, global.WechatCache)
	zap.L().Info("工具类初始化成功")

	// 12. 初始化控制器和路由
	router, registry := initialize.InitRouter(services, utils)
	zap.L().Info("路由初始化成功")

	// 设置全局控制器注册表
	global.ControllerRegistry = registry

	// 12.1 初始化菜单
	if err := initialize.InitMenus(registry, global.DB); err != nil {
		zap.L().Error("菜单初始化失败", zap.Error(err))
	} else {
		zap.L().Info("菜单初始化成功")
	}

	// 添加一个简单的路由来测试CORS
	router.GET("/test-cors", func(c *gin.Context) {
		// 设置CORS头
		c.Writer.Header().Set("Access-Control-Allow-Origin", c.Request.Header.Get("Origin"))
		c.Writer.Header().Set("Access-Control-Allow-Credentials", "true")
		c.Writer.Header().Set("Access-Control-Allow-Headers", "Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization, accept, origin, Cache-Control, X-Requested-With")
		c.Writer.Header().Set("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS")

		// 返回一个简单的响应
		c.JSON(200, gin.H{
			"message": "CORS test successful",
		})
	})

	// 添加一个测试CSRF的API端点
	router.GET("/test-csrf", func(c *gin.Context) {
		// 设置CORS头
		c.Writer.Header().Set("Access-Control-Allow-Origin", c.Request.Header.Get("Origin"))
		c.Writer.Header().Set("Access-Control-Allow-Credentials", "true")
		c.Writer.Header().Set("Access-Control-Allow-Headers", "Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization, accept, origin, Cache-Control, X-Requested-With")
		c.Writer.Header().Set("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS")

		// 获取CSRF令牌
		token := c.GetHeader("X-CSRF-Token")
		csrfCookie, _ := c.Cookie("csrf_token")

		zap.L().Info("CSRF测试",
			zap.String("header_token", token),
			zap.String("cookie_token", csrfCookie))

		// 生成新的CSRF令牌
		newToken, err := middleware.GenerateCSRFToken(c)
		if err != nil {
			zap.L().Error("生成CSRF令牌失败", zap.Error(err))
		} else {
			// 设置CSRF Cookie
			middleware.SetCSRFCookie(c, newToken, middleware.CSRFConfig{
				CookieName:     "csrf_token",
				CookiePath:     "/",
				CookieMaxAge:   86400,
				CookieHTTPOnly: false,
			})
			zap.L().Info("已生成新的CSRF令牌", zap.String("new_token", newToken))
		}

		c.JSON(200, gin.H{
			"message":      "CSRF测试",
			"header_token": token,
			"cookie_token": csrfCookie,
			"csrf_valid":   token != "" && csrfCookie != "" && token == csrfCookie,
			"new_token":    newToken,
		})
	})

	router.OPTIONS("/test-csrf", func(c *gin.Context) {
		// 设置CORS头
		c.Writer.Header().Set("Access-Control-Allow-Origin", c.Request.Header.Get("Origin"))
		c.Writer.Header().Set("Access-Control-Allow-Credentials", "true")
		c.Writer.Header().Set("Access-Control-Allow-Headers", "Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization, accept, origin, Cache-Control, X-Requested-With")
		c.Writer.Header().Set("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS")
		c.Writer.Header().Set("Access-Control-Max-Age", "86400") // 24小时

		c.AbortWithStatus(204)
	})

	router.POST("/test-csrf", func(c *gin.Context) {
		// 设置CORS头
		c.Writer.Header().Set("Access-Control-Allow-Origin", c.Request.Header.Get("Origin"))
		c.Writer.Header().Set("Access-Control-Allow-Credentials", "true")
		c.Writer.Header().Set("Access-Control-Allow-Headers", "Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization, accept, origin, Cache-Control, X-Requested-With")
		c.Writer.Header().Set("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS")

		// 获取CSRF令牌
		token := c.GetHeader("X-CSRF-Token")
		csrfCookie, _ := c.Cookie("csrf_token")

		// 获取请求体
		var requestBody map[string]interface{}
		if err := c.ShouldBindJSON(&requestBody); err != nil {
			zap.L().Error("解析请求体失败", zap.Error(err))
		}

		zap.L().Info("CSRF POST测试",
			zap.String("header_token", token),
			zap.String("cookie_token", csrfCookie),
			zap.Any("request_body", requestBody))

		// 手动验证CSRF令牌
		valid := token != "" && csrfCookie != "" && token == csrfCookie

		// 即使验证失败也返回200状态码，但在响应中指明验证结果
		// 这样前端可以显示结果而不是处理HTTP错误
		message := "CSRF验证失败"
		if valid {
			message = "CSRF POST测试成功"
		}

		c.JSON(200, gin.H{
			"message":      message,
			"header_token": token,
			"cookie_token": csrfCookie,
			"csrf_valid":   valid,
		})
	})

	// 13. 启动HTTP服务器
	server := &http.Server{
		Addr:    fmt.Sprintf(":%d", global.Config.App.Port),
		Handler: router,
	}

	// 在goroutine中启动服务器，这样它就不会阻塞
	go func() {
		zap.L().Info("HTTP服务器启动成功",
			zap.String("应用名称", global.Config.App.Name),
			zap.String("版本", global.Config.App.Version),
			zap.String("运行模式", global.Config.App.Mode),
			zap.Int("端口", global.Config.App.Port),
		)

		if err := server.ListenAndServe(); err != nil && err != http.ErrServerClosed {
			zap.L().Fatal("HTTP服务器启动失败", zap.Error(err))
		}
	}()

	// 13. 等待中断信号优雅关闭服务器
	quit := make(chan os.Signal, 1)
	signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)
	<-quit

	zap.L().Info("正在关闭服务...")

	// 创建一个5秒的上下文用于超时
	ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
	defer cancel()

	// 优雅关闭HTTP服务器
	if err := server.Shutdown(ctx); err != nil {
		zap.L().Fatal("服务器关闭异常", zap.Error(err))
	}

	// 关闭配置监听
	config.Shutdown()

	// 关闭调度器
	if scheduler, ok := global.Scheduler.(interface{ Stop() }); ok {
		scheduler.Stop()
		zap.L().Info("调度器已关闭")
	}

	// 关闭消息队列
	if mq, ok := global.MessageQueue.(interface{ Close() error }); ok {
		if err := mq.Close(); err != nil {
			zap.L().Error("消息队列关闭异常", zap.Error(err))
		} else {
			zap.L().Info("消息队列已关闭")
		}
	}

	// 关闭Redis连接
	if err := global.Redis.Close(); err != nil {
		zap.L().Error("Redis关闭异常", zap.Error(err))
	}

	zap.L().Info("服务已关闭")
}
